//
//  InstallationScanBarcodeDynamsoftView.swift
//  ezyform
//
//  Created by Moennig Q on 15/10/2022.
//  Copyright © 2022 Client.Solution Pty Ltd. All rights reserved.
//

import UIKit
struct ScannedBarcodeModel {
    var barcode: String = ""
    var validFlag: Bool = true//是否符合长度，或正则表达式校验
    var uploadedFlag: Bool = false//是否上传成功，true表示上传成功
}
class ScannerCommonUIView: UIView {
    var doneOnKeyboarkClickFlag: Bool = false
    var deleteBarcodeClosure: ((String) -> Void)?
    var manuallyConfirmClosure: ((String) -> Void)?
    var takePhotoBtnClickClosure: (()->Void)?
    var switchAddMethodBtnClickClosure: (()->Void)?
    var switchTorchBtnClickClosure: (()->Void)?
    var switchScanModeBtnClickClosure: (()->Void)?
    var cancelBtnClickClosure: (()->Void)?
    //是否是原生扫描
    var nativeScanFlag: Bool = false
    //扫描panel还是inverter
    var scanningType: ScanningType = .panel
    var scannedBarcodeList = [ScannedBarcodeModel]()
    let backgroundImageView = UIImageView()
    //background
    let cropLayer = CAShapeLayer()
    lazy var backgroundView: UIView = {
        let aView = UIView(frame: CGRect(x: 0, y: 0, width: APPConfig.WidthForPortrait, height: APPConfig.HeightForPortrait))
        aView.backgroundColor = UIColor.clear
        aView.layer.addSublayer(cropLayer)
        let path = CGMutablePath()
        path.addRect(aView.bounds)
        cropLayer.fillRule = CAShapeLayerFillRule.evenOdd
        cropLayer.fillColor = UIColor.black.withAlphaComponent(0.9).cgColor
        return aView
    }()
    lazy var barcodeCntLabel: BaseLabel = {
        let barcodeCntLabel = BaseLabel()
        return barcodeCntLabel
    }()
    lazy var invalidOrDuplicatedTipLabel: BaseLabel = {
        let invalidOrDuplicatedTipLabel = BaseLabel()
        invalidOrDuplicatedTipLabel.textAlignment = .center
        invalidOrDuplicatedTipLabel.backgroundColor = .clear
        invalidOrDuplicatedTipLabel.setFont(R.font.sfProTextSemibold(size: 20))
        return invalidOrDuplicatedTipLabel
    }()
    
    lazy var cancelBtn: UIButton = {
        let cancelBtn = UIButton(frame: CGRect.zero)
        cancelBtn.setImage(UIImage(named: "service_myjob_takephoto_btn_return"), for: UIControl.State.normal)
        return cancelBtn
    }()
    lazy var torchBtn: UIButton = {
        let torchBtn = UIButton()
        torchBtn.setImage(UIImage(named: "installation_detail_panelnumber_scanbarcode_torch_off"), for: UIControl.State.normal)
        torchBtn.backgroundColor = UIColor.clear
        torchBtn.clipsToBounds = true
        
        return torchBtn
    }()
    lazy var switchScanModeBtn: UIButton = {
        let btn = UIButton()
        btn.backgroundColor = UIColor.clear
        btn.clipsToBounds = true
        
        return btn
    }()
    lazy var settingBtn: UIButton = {
        let btn = UIButton()
        btn.backgroundColor = UIColor.clear
        btn.clipsToBounds = true
        btn.setImage(UIImage(named: "scanner_setting"), for: UIControl.State.normal)
        return btn
    }()
    lazy var switchAddMethodBtn: BaseButton = {
        let btn = BaseButton()
        btn.setTitleColor(UIColor.white, for: UIControl.State.normal)
        btn.setFont(R.font.interMedium(size: 15))
        btn.backgroundColor = UIColor.clear
        btn.clipsToBounds = true
        return btn
    }()

    lazy var scanView: UIView = {
        let aView = UIView()
        aView.backgroundColor = UIColor.clear
        return aView
    }()
    lazy var noAvailableDeviceLabel: BaseLabel = {
        let label = BaseLabel()
        label.text = R.string.localizable.noCameraAvailable()
        label.textColor = .red
        label.setFont(R.font.sfProTextSemibold(size: 20))
        label.backgroundColor = .clear
        return label
    }()
    lazy var tableView: UITableView = {
        let aView = UITableView()
        aView.showsVerticalScrollIndicator = false
        aView.backgroundColor = UIColor.clear
        
        return aView
    }()
    
    
    //setting view
    lazy var settingView: ScanerSettingView = {
        let aView = ScanerSettingView()
        
        return aView
    }()
    //MARK: - 手工添加时的编辑框
    lazy var codeTexfield: BaseTextField = {
        let aView = BaseTextField()
        aView.backgroundColor = .black
        aView.borderStyle = .roundedRect
        aView.layer.cornerRadius = 6
        aView.layer.borderWidth = 1
        aView.layer.borderColor = UIColor(hexStr: "#FFFFFFCC").cgColor
        aView.textColor = .white//不可编辑是黑色背景，白色字体
        aView.tintColor = .white//光标颜色
        aView.returnKeyType = .done
        aView.clearButtonMode = .whileEditing
        aView.setFont(R.font.sfProTextRegular(size: 16))
        aView.isUserInteractionEnabled = true
        return aView
    }()
    lazy var codeTexfieldDisabled: BaseTextField = {
        let aView = BaseTextField()
        aView.backgroundColor = UIColor(hexStr: "#EAEAEA99")
        aView.borderStyle = .roundedRect
        aView.layer.cornerRadius = Constant.StandardCornerRadius
        aView.layer.borderWidth = 1
        aView.layer.borderColor = UIColor(hexStr: "#FFFFFFCC").cgColor
        aView.textColor = UIColor(hexStr: "#FFFFFF66")
        aView.isUserInteractionEnabled = false
        return aView
    }()
    //MARK: - 手工添加时的拍照按钮
    lazy var takePhotoImageView: UIImageView = {
        let aView = UIImageView(image: UIImage(named: "service_myjob_takephoto_btn_takephoto"))
        aView.contentMode = .scaleToFill
        return aView
    }()
    //MARK: - 手工增加拍照后再编辑的提示语
    lazy var manuallyTakePhotoTipMsgLabel: BaseLabel = {
        let label = BaseLabel()
        label.text = "Take photo and input serial number"
        label.textColor = UIColor(hexStr: "#FFFFFF99")
        label.setFont(R.font.sfProTextMedium(size: 15))
        label.backgroundColor = .clear
        return label
    }()
    //MARK: - 预览照片
    lazy var codeImageView: UIImageView = {
        let aView = UIImageView()
        return aView
    }()
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    init(_ type: ScanningType,nativeScanFlag: Bool = false) {
        super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
        self.scanningType = type
        self.nativeScanFlag = nativeScanFlag
        self.setUpView()
        self.setAllTouchupEvent()
    }
    private func setAllTouchupEvent(){
        self.settingBtn.addTarget(self, action: #selector(settingBtnClick), for: UIControl.Event.touchUpInside)
        self.cancelBtn.addTarget(self, action: #selector(cancelBtnClick), for: UIControl.Event.touchUpInside)
        self.torchBtn.addTarget(self, action: #selector(openTorch), for: UIControl.Event.touchUpInside)
        self.switchScanModeBtn.addTarget(self, action: #selector(switchScanModeBtnClick), for: UIControl.Event.touchUpInside)
        self.switchAddMethodBtn.addTarget(self, action: #selector(switchAddMethodBtnClick), for: UIControl.Event.touchUpInside)
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(takePhotoImageViewClick))
        self.takePhotoImageView.addGestureRecognizer(tapGesture)
        self.takePhotoImageView.isUserInteractionEnabled = true
    }
    
    //改变
    private func switchCropLayer(_ scanMode: ScanMode){
        let path = CGMutablePath()
        path.addRect(backgroundView.bounds)
        let cropRect = ScanResultImageTool().getCropRect(scanMode)
        path.addRect(cropRect)
        self.cropLayer.path = path
    }
    private func setUpView(_ scanMode: ScanMode = .oneD){
        self.addSubview(backgroundView)
        self.switchCropLayer(scanMode)
        backgroundView.addSubview(scanView)
        //预览手动增加时，takePhoto的扫描区域的图片
        self.codeImageView.contentMode = .scaleAspectFit
        self.scanView.addSubview(self.codeImageView)
        self.codeImageView.snp.makeConstraints { make in
            make.left.top.equalTo(ScanResultImageTool().margin)
            make.right.bottom.equalTo(-ScanResultImageTool().margin)
        }
        //topBackView
        let topBackView = UIView()
        topBackView.backgroundColor = UIColor(hexStr: "#A9ABAD")
        backgroundView.addSubview(topBackView)
        topBackView.snp.makeConstraints { make in
            make.top.left.right.equalToSuperview()
            make.height.equalTo(APPConfig.scanViewTopMargin)
        }
        //
        backgroundImageView.contentMode = .scaleToFill
        topBackView.addSubview(backgroundImageView)
        backgroundImageView.snp.makeConstraints { make in
            make.top.equalTo(APPConfig.backgroundImageTopMargin)
            make.left.equalToSuperview().offset(APPConfig.backgroundImageLeftRightMargin)
            make.right.equalToSuperview().offset(-APPConfig.backgroundImageLeftRightMargin)
            make.height.greaterThanOrEqualTo(0)
            make.bottom.equalTo(-APPConfig.backgroundImageBottomMargin)
        }
        //
        let topBackViewBottomView = UIView()
        topBackViewBottomView.drawCorner(byRoundingCorners: [.topLeft,.topRight], backColorHexStr: "#000000")
        topBackView.addSubview(topBackViewBottomView)
        topBackViewBottomView.snp.makeConstraints { make in
            make.height.equalTo(APPConfig.backgroundImageBottomMargin)
            make.left.right.bottom.equalToSuperview()
        }
        topBackView.addSubview(switchAddMethodBtn)
        switchAddMethodBtn.snp.makeConstraints { make in
            make.top.equalTo(backgroundImageView)
            make.right.equalTo(backgroundImageView)
            make.height.equalTo(40)
            make.width.greaterThanOrEqualTo(50)
        }
        //
        scanView.addSubview(invalidOrDuplicatedTipLabel)
        invalidOrDuplicatedTipLabel.snp.makeConstraints { (make) in
            make.size.greaterThanOrEqualTo(0)
            make.centerX.equalToSuperview()
            make.bottom.equalTo(scanView).offset(-20)
        }
        //corner image 1
        let imageViewOne = UIImageView(image: UIImage(named: "installation_detail_panelnumber_scan_one"))
        scanView.addSubview(imageViewOne)
        imageViewOne.snp.makeConstraints { (make) in
            make.left.top.equalToSuperview()
            make.width.equalTo(23)
            make.height.equalTo(24)
        }
        //corner image 2
        let imageViewTwo = UIImageView(image: UIImage(named: "installation_detail_panelnumber_scan_two"))
        scanView.addSubview(imageViewTwo)
        imageViewTwo.snp.makeConstraints { (make) in
            make.right.top.equalToSuperview()
            make.width.equalTo(23)
            make.height.equalTo(24)
        }
        //corner image 3
        let imageViewThree = UIImageView(image: UIImage(named: "installation_detail_panelnumber_scan_three"))
        scanView.addSubview(imageViewThree)
        imageViewThree.snp.makeConstraints { (make) in
            make.right.bottom.equalToSuperview()
            make.width.equalTo(23)
            make.height.equalTo(24)
        }
        //corner image 3
        let imageViewFour = UIImageView(image: UIImage(named: "installation_detail_panelnumber_scan_four"))
        scanView.addSubview(imageViewFour)
        imageViewFour.snp.makeConstraints { (make) in
            make.left.bottom.equalToSuperview()
            make.width.equalTo(23)
            make.height.equalTo(24)
        }
        //manuallyRecognizedMsgLabel
        backgroundView.addSubview(manuallyTakePhotoTipMsgLabel)
        manuallyTakePhotoTipMsgLabel.snp.makeConstraints { make in
            make.top.equalTo(scanView.snp.bottom)
            make.centerX.equalToSuperview()
            make.height.width.equalTo(0)
        }
        //codeTextfield
        backgroundView.addSubview(codeTexfield)
        codeTexfield.snp.makeConstraints { make in
            make.top.equalTo(manuallyTakePhotoTipMsgLabel.snp.bottom)
            make.left.equalTo(16)
            make.right.equalTo(-16)
            make.height.equalTo(0)
        }
        //用于显示take photo的编辑框UI，用UIView替代，因为UITextfield来回切换textColor偶尔不生效
        backgroundView.addSubview(codeTexfieldDisabled)
        codeTexfieldDisabled.snp.makeConstraints { make in
            make.edges.equalTo(codeTexfield)
        }
        //barcode cnt label
        backgroundView.addSubview(barcodeCntLabel)
        barcodeCntLabel.snp.makeConstraints { (make) in
            make.top.equalTo(codeTexfield.snp.bottom).offset(20)
            make.left.equalTo(30)
            make.width.height.greaterThanOrEqualTo(0)
        }
        //lineView
        let lineView = UIView()
        lineView.backgroundColor = UIColor(hexStr: "#FFFFFF33")
        backgroundView.addSubview(lineView)
        lineView.snp.makeConstraints { make in
            make.top.equalTo(barcodeCntLabel.snp.bottom).offset(10)
            make.left.equalTo(barcodeCntLabel)
            make.right.equalTo(-30)
            make.height.equalTo(1)
        }
        
        //1.bottom view
        let bottomView = UIView()
        bottomView.drawCorner(byRoundingCorners: [.topLeft,.topRight],backColorHexStr: "#005D2DFF")
        backgroundView.addSubview(bottomView)
        bottomView.snp.makeConstraints { (make) in
            make.left.right.bottom.equalToSuperview()
            make.height.equalTo(90)
        }

        //1.1cancel btn
        bottomView.addSubview(cancelBtn)
        cancelBtn.snp.makeConstraints { (make) in
            make.left.equalToSuperview().offset(20)
            make.top.equalTo(16)
            make.width.equalTo(46)
            make.height.equalTo(32)
        }
        //1.2torch btn
        bottomView.addSubview(self.torchBtn)
        self.torchBtn.snp.makeConstraints { (make) in
            make.centerY.equalTo(cancelBtn)
            make.left.equalTo(cancelBtn.snp.right).offset(24)
            make.width.height.equalTo(32)
        }
        
        //1.2 settingsBtn
        bottomView.addSubview(self.settingBtn)
        settingBtn.snp.makeConstraints { (make) in
            make.centerY.size.equalTo(torchBtn)
            make.right.equalToSuperview().offset(-20)
        }
        //switchScanModeBtn
        bottomView.addSubview(switchScanModeBtn)
        switchScanModeBtn.snp.makeConstraints { (make) in
            make.right.equalTo(settingBtn.snp.left).offset(-24)
            make.size.centerY.equalTo(torchBtn)
        }
        //takePhotoBtn
        bottomView.addSubview(takePhotoImageView)
        takePhotoImageView.snp.makeConstraints { (make) in
            make.height.width.equalTo(50)
            make.centerX.equalToSuperview()
            make.centerY.equalTo(torchBtn)
            
        }
        //没有有效设备的提示信息
        noAvailableDeviceLabel.isHidden = true
        scanView.addSubview(noAvailableDeviceLabel)
        noAvailableDeviceLabel.snp.makeConstraints { (make) in
            make.width.height.greaterThanOrEqualTo(0)
            make.center.equalToSuperview()
        }
        //table view
        backgroundView.addSubview(tableView)
        tableView.snp.makeConstraints { (make) in
            make.top.equalTo(lineView.snp.bottom).offset(10)
            make.left.right.equalTo(lineView)
            make.bottom.equalTo(bottomView.snp.top).offset(-2)
        }
        //设置扫描指导背景图
        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(ScanBarcodeRecoganizedTableViewCell.self, forCellReuseIdentifier: ScanBarcodeRecoganizedTableViewCell.reuseCellIdentifier)
        tableView.separatorStyle = .none
        //
        //扫描模式
        self.switchScanMode(scanMode)
        //定制panel或inverter的UI
        self.switchUIByScanType()
        self.codeTexfield.delegate = self
        //隐藏系统键盘上的UIToolbar
        self.codeTexfield.inputAccessoryView = UIView()
        self.codeTexfield.isHidden = true
        self.codeTexfieldDisabled.isHidden = false
        self.codeTexfield.isUserInteractionEnabled = false
        self.codeTexfieldDisabled.isUserInteractionEnabled = false//不可交互
    }
    //MARK: - 显示setting UI
    @objc func settingBtnClick(){
        if settingView.superview == nil{
            self.addSubview(settingView)
            settingView.frame = self.frame
        }
    }
    @objc func cancelBtnClick(){
        self.cancelBtnClickClosure?()
    }
    
    @objc func switchScanModeBtnClick(){
        self.switchScanModeBtnClickClosure?()
    }
    @objc func switchAddMethodBtnClick(){
        self.switchAddMethodBtnClickClosure?()
    }
    @objc func takePhotoImageViewClick(){
        self.takePhotoBtnClickClosure?()
    }
    @objc func openTorch(){
        self.switchTorchBtnClickClosure?()
    }
    
    func switchUIByScanType(){
        var imageName = ""
        switch self.scanningType{
        case .panel:
            imageName = "Installation_detail_scan_panel_background"
        case .inverter:
            imageName = "Installation_detail_scan_inverter_background"
        case .tank:
            imageName = "Installation_detail_scan_tank_background"
        }
        backgroundImageView.image = UIImage(named: imageName)
    }
    func switchTorchBtn(_ onFlag: Bool){
        let imageName: String = (onFlag ? "installation_detail_panelnumber_scanbarcode_torch_on" : "installation_detail_panelnumber_scanbarcode_torch_off")
        self.torchBtn.setImage(UIImage(named: imageName), for: UIControl.State.normal)
    }
    //MARK: - 切换条形码或二维码
    func switchScanMode(_ scanMode: ScanMode){
        let imageName: String = (scanMode == .oneD ? "installation_detail_panelnumber_scanbarcode_qr" : "installation_detail_panelnumber_scanbarcode_oned")
        switchScanModeBtn.setImage(UIImage(named: imageName), for: UIControl.State.normal)
        self.switchCropLayer(scanMode)
        self.scanView.frame = ScanResultImageTool().getScanFrameRect(scanMode)
    }
    //MARK: - 切换自动识别或手动增加
    func switchScanAddMethodMode(_ addMethod: ScanAddMethodMode){
        self.codeTexfield.resignFirstResponder()
        self.codeTexfield.text = ""
        self.codeTexfieldDisabled.text = ""
        if addMethod == .auto {
            self.switchAddMethodBtn.setTitle("Manually", for: UIControl.State.normal)
            self.takePhotoImageView.image = nil
            self.takePhotoImageView.isUserInteractionEnabled = false
            self.codeTexfield.isHidden = true
            manuallyTakePhotoTipMsgLabel.snp.remakeConstraints { make in
                make.top.equalTo(scanView.snp.bottom)
                make.centerX.equalToSuperview()
                make.height.width.equalTo(0)
            }
            codeTexfield.snp.remakeConstraints { make in
                make.top.equalTo(manuallyTakePhotoTipMsgLabel.snp.bottom)
                make.left.equalTo(16)
                make.right.equalTo(-16)
                make.height.equalTo(0)
            }
        }else{
            self.switchAddMethodBtn.setTitle("Auto", for: UIControl.State.normal)
            self.takePhotoImageView.image = UIImage(named: "service_myjob_takephoto_btn_takephoto")
            self.takePhotoImageView.isUserInteractionEnabled = true
            self.codeTexfield.isHidden = false
            manuallyTakePhotoTipMsgLabel.snp.remakeConstraints { make in
                make.top.equalTo(scanView.snp.bottom)
                make.centerX.equalToSuperview()
                make.width.greaterThanOrEqualTo(0)
                make.height.equalTo(40)
            }
            codeTexfield.snp.remakeConstraints { make in
                make.top.equalTo(manuallyTakePhotoTipMsgLabel.snp.bottom)
                make.left.equalTo(16)
                make.right.equalTo(-16)
                make.height.equalTo(44)
            }
            self.codeTexfield.text = ""
        }
    }
    func showUnavailableDeviceMsg(_ availableFlag: Bool){
        self.noAvailableDeviceLabel.isHidden = availableFlag
    }
    func showInvalidMsg(_ msg: String){
        self.invalidOrDuplicatedTipLabel.textColor = UIColor(hexStr: "#FFBA0A")
        self.invalidOrDuplicatedTipLabel.alpha = 1
        self.invalidOrDuplicatedTipLabel.text = msg
        UIView.transition(with: self.invalidOrDuplicatedTipLabel, duration: 1, options: UIView.AnimationOptions.curveEaseInOut, animations: {
            self.invalidOrDuplicatedTipLabel.alpha = 0
        })
    }
    func showDuplicatedMsg(_ msg: String){
        self.invalidOrDuplicatedTipLabel.textColor = UIColor(hexStr: "#54EE07")
        self.invalidOrDuplicatedTipLabel.alpha = 1
        self.invalidOrDuplicatedTipLabel.text = msg
        UIView.transition(with: self.invalidOrDuplicatedTipLabel, duration: 1, options: UIView.AnimationOptions.curveEaseInOut, animations: {
            self.invalidOrDuplicatedTipLabel.alpha = 0
        })
    }
    //MARK: - 显示重复提示，且如果重复的在tableview中有就红色闪烁提示
    func showDuplicatedEffect(_ barcode: String, scannedIndex: Int?){
        self.showDuplicatedMsg("Duplicated")
        //重复的标橙色
        if let duplicatedIndex = scannedIndex{
            self.tableView.scrollToRow(at: IndexPath(row: duplicatedIndex, section: 0), at: UITableView.ScrollPosition.middle, animated: false)
            if let cell = self.tableView.cellForRow(at: IndexPath(row: duplicatedIndex, section: 0)) as? ScanBarcodeRecoganizedTableViewCell {
                cell.barcodeLabel.textColor = .orange

                let delay = Double(1) * Double(NSEC_PER_SEC)
                let time = DispatchTime.now() + Double(Int64(delay)) / Double(NSEC_PER_SEC)
                DispatchQueue.main.asyncAfter(deadline: time) {
                    var validFlag: Bool = true
                    if self.scanningType == .panel {
                        validFlag = Tool().isValidPanelNumber(str: barcode)
                    }else{
                        validFlag = Tool().isValidInverterNumber(str: barcode)
                    }
                    if validFlag {
                        cell.barcodeLabel.textColor = .white
                    }else{
                        cell.barcodeLabel.textColor = .red
                    }
                }
            }
        }
    }
    
    func setBarcodeCountText(_ scannedCnt: Int, planCntStr: String){
        let subContent = "\(scannedCnt)/"
        let content = subContent + planCntStr
        let range = (content as NSString).range(of: subContent)
        let attrString = NSMutableAttributedString(string: content)
        let attr1: [NSMutableAttributedString.Key: Any] = [.foregroundColor: UIColor.white]
        let attr2: [NSMutableAttributedString.Key: Any] = [.foregroundColor: UIColor.white.withAlphaComponent(0.6)]
        
        attrString.addAttributes(attr1, range: NSRange(location: 0, length: content.count))
        attrString.addAttributes(attr2, range: NSRange(location: range.location, length: range.length))
        self.barcodeCntLabel.attributedText = attrString
        self.barcodeCntLabel.setFont(R.font.sfProTextMedium(size: 15))
    }
    func setBarcodeText(_ code: String){
        codeTexfieldDisabled.text = code
    }
    func clearCodeTextField(){
        codeTexfield.text = ""
        codeTexfieldDisabled.text = ""
        codeTexfield.resignFirstResponder()
        codeTexfield.isHidden = true
        codeTexfieldDisabled.isHidden = false
        codeTexfield.isUserInteractionEnabled = false
    }
    func enableCodeTextField(){
        codeTexfield.text = codeTexfieldDisabled.text
        codeTexfieldDisabled.text = ""
        codeTexfield.isUserInteractionEnabled = true
        codeTexfield.isHidden = false
        codeTexfieldDisabled.isHidden = true
        codeTexfield.becomeFirstResponder()
    }
    //MARK: - take photo后显示预览图片
    func showTakePhotoImage(_ scanMode: ScanMode, imageData: Data){
        if let image = UIImage(data: imageData){
            if let cropImage = self.cropImage(fromImage: image, scanMode: scanMode){
                self.codeImageView.isHidden = false
                self.codeImageView.image = cropImage
            }
        }
    }
    //MARK: - 清除预览图片
    func clearTakePhotoImage(){
        self.codeImageView.image = nil
        self.codeImageView.isHidden = true
    }
    //MARK: - takePhoto时，获取识别区域的图片覆盖在扫描区域，模拟相机暂停的功能
    private func cropImage(fromImage: UIImage, scanMode: ScanMode ) -> UIImage? {
        if let scaleImage = ScanResultImageTool().downscaleImage(image: fromImage, toSize: UIScreen.main.bounds.size){
            let scale = UIScreen.main.scale
            //第二步：剪切图片，注意：cropping中的参数是像素点，所有要乘以PPI,剪切图片的Height，扩展到线框以下scanViewTopMargin
            //Perform cropping in Core Graphics
            let cropRect = ScanResultImageTool().getCropRect(scanMode)
            guard let cutImageRef: CGImage = scaleImage.cgImage?.cropping(to: CGRect(x: cropRect.origin.x * scale, y: cropRect.origin.y * scale, width: cropRect.width * scale, height: cropRect.height * scale))
                else {
                    return nil
            }
            // Return image to UIImage
            let croppedImage: UIImage = UIImage(cgImage: cutImageRef)
            return croppedImage
        }
        return nil
    }
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}
extension ScannerCommonUIView: UITableViewDataSource , UITableViewDelegate,UITextFieldDelegate{
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.scannedBarcodeList.count
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 30
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        var cell : ScanBarcodeRecoganizedTableViewCell! = tableView.dequeueReusableCell(withIdentifier: ScanBarcodeRecoganizedTableViewCell.reuseCellIdentifier) as? ScanBarcodeRecoganizedTableViewCell
        if (cell == nil){
            cell = ScanBarcodeRecoganizedTableViewCell(style: .default, reuseIdentifier: ScanBarcodeRecoganizedTableViewCell.reuseCellIdentifier)
        }
        let code = self.scannedBarcodeList[indexPath.row].barcode
        cell.deleteClosure = {[weak self] in
            guard let strongSelf = self else { return  }
            //闭包中不要用到indexPath，tableView刷新后此值被固定，在点击删除的时候可能会越界导致crash
            strongSelf.deleteBarcodeClosure?(code)
        }
        cell.setData(indexPath.row, list: self.scannedBarcodeList)
        return cell
    }
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        self.doneOnKeyboarkClickFlag = true
        textField.resignFirstResponder()
        return true
    }
    //编辑完成时
    func textFieldDidEndEditing(_ textField: UITextField) {
        var code: String = ""//直接关闭键盘返回的code为空，即不处理
        if self.doneOnKeyboarkClickFlag {//点击Done按钮，保存code
            code = (textField.text ?? "").trimmingCharacters(in: .whitespaces)
        }
        self.manuallyConfirmClosure?(code)
        self.doneOnKeyboarkClickFlag = false
    }
    func deleteOneRow(_ code: String){
        if let indexRow = self.scannedBarcodeList.firstIndex(where: { $0.barcode == code}){
            self.scannedBarcodeList.remove(at: indexRow)
            self.tableView.deleteRows(at: [IndexPath(row: indexRow, section: 0)], with: UITableView.RowAnimation.none)
        }
    }
}
